//
// Created by Rory on 2020/11/6.
//

#define GENERATE_TEST_FUNC_SIGNATURE
#include "../common.h"

/**
 * 反序输出一个四位数，要求只能用一个整型变量接收输入
 * @param x
 * @return
 * 分析：结束条件是形参为个位数，即<10。需要注意的点是printf("%d",x%10)要放在递归调用语句前面。
 * 经验教训：手写代码后必须自己模拟运行一遍，不断修正代码
 */
void Reverse(int x){
    if (x >= 10){
        printf("%d",x % 10);
        Reverse(x / 10);
    }else{
        printf("%d",x);
    }
}

TestFunc(Reverse){
    int x;

    printf("输入一个四位数字：");
    scanf("%d",&x);
    Reverse(x);

}

/**
 * 判断str是否为回文（正反都一样）,str必须以'@'字符结尾
 * @param str
 * @return
 */
bool IsPalindrome(const char* str){
    int start=0,end=0;
    const char* p = str;
    //计算字符串长度
    while (*str++ != '@'){
        end++;
    }
    //空字符串算作回文
    if(end == 0){
        return true;
    }
    //对比
    end--;//将end的语义更改为索引
    while (end-start >= 0){
        if(p[start++] != p[end--]){
            return false;
        }
    }
    return true;
}

TestFunc(IsPalindrome){
    char *str1 = "abba@";
    char *str2 = "abbaa@";
    char *str3 = "a@";

    printf("%s\n",IsPalindrome(str1)==true?"true":"false");
    printf("%s\n",IsPalindrome(str2)==true?"true":"false");
    printf("%s\n",IsPalindrome(str3)==true?"true":"false");
}


/**
 * 打印由*组成的实体等腰三角形，并将其输入到文件star.txt中
 * @param n 打印的行数
 */
void PrintStarTriAngle(int n){
    int starNumberOfLastLine = 2*n - 1;//最后一行的星星数，用于计算某行的空格数
    int preStarNumber;//第i-1行*的数量
    int starNumber;//第i行*的数量，第一行默认为1，计算公式为S[i] = S[i-1] + 2，其中S[1] = 1
    int halfSpaceNumber;//第i行空格的数量的一半，计算公式为(S[n]-S[i])/2
    int currentLine = 0;
    FILE* file;
    if( !(file = fopen("./star.txt","w")) ){
        printf("创建或打开文件错误!");
        exit(0);
    }


    while (currentLine++ != n){
        //计算第i行星星的数量
        if (currentLine==1){
            preStarNumber = starNumber = 1;
        }else{
            starNumber = preStarNumber + 2;
        }
        //计算第i行空格的数量
        halfSpaceNumber = (starNumberOfLastLine - starNumber)/2;

        //打印
        for (int i = 0; i < halfSpaceNumber; ++i) {
            printf(" ");
            //fwrite(" ",sizeof(" "),1,file);
            fputc(' ',file);
        }
        for (int i = 0; i < starNumber; ++i) {
            printf("*");
            //fwrite("*",sizeof("*"),1,file);
            fputc('*',file);
        }
        for (int i = 0; i < halfSpaceNumber; ++i) {
            printf(" ");
            //fwrite(" ",sizeof(" "),1,file);
            fputc(' ',file);

        }
        printf("\n");
        //fwrite("\n",sizeof("\n"),1,file);
        fputc('\n',file);

        preStarNumber = starNumber;
    }
    fclose(file);
}

TestFunc(PrintStarTriAngle){
    //PrintStarTriAngle(1);
    //PrintStarTriAngle(5);
    //PrintStarTriAngle(10);
}

/**
 * 计算PI的值，递推公式为：4/pi = 1 - 1/3 + 1/5 - 1/7 + ...
 * 精确到最后一项绝对值小于1e-6
 */
void CountingPi(){
    double sum = 1;
    double i = 1;//第i项的绝对值
    double signal = -1;//第i项的符号

    while (1.0f/i > 1e-6){
        i += 2;
        sum += 1.0f / i*signal;
        signal = -signal;
    }
    printf("%.4f",4.0f * sum);
}

TestFunc(CountingPi){
    CountingPi();
}


/**
 * 从键盘输入学生记录并输出到文件中
 */
typedef struct {
    long ID;
    char name[10];
    float scores[3];//三门课程分数
    float average;//平均分
}Student;

void WriteStudentInfoToFile(){
    int n;//学生信息条数
    printf("信息条数：");
    scanf("%d",&n);

    Student s;
    FILE* fp;
    if((fp=fopen("./student.txt","w")) == NULL){
        perror("读取文件出错!");
        exit(-1);
    }
    int i = 0;//第i条记录
    while (i++ < n){
        fscanf(stdin,"%10ld%8s%4f%4f%4f",&s.ID,s.name,
                &s.scores[0],&s.scores[1],&s.scores[2]);
        s.average = (s.scores[0] + s.scores[1] + s.scores[2]) / 3;
        fprintf(stdout,"%-10ld%-8s%-6.1f%-6.1f%-6.1f%-6.1f\n",s.ID,s.name,
                s.scores[0],s.scores[1],s.scores[2],s.average);
        fprintf(fp,"%-10ld%-8s%-6.1f%-6.1f%-6.1f%-6.1f\n",s.ID,s.name,
               s.scores[0],s.scores[1],s.scores[2],s.average);
    }
}

TestFunc(WriteStudentInfoToFile){
    WriteStudentInfoToFile();
}

typedef struct {
    int score;
}S;
int main(){
    /**
     * result : 测试符合预期
     * date : 11-6 20:43
     */
    //InvokeFunc(Reverse);

    /**
     * result : accepted
     * date : 11-6 20:56
     */
    //InvokeFunc(IsPalindrome);

    /**
     * result : perfect
     * date : 11-11 20:38
     */
    //InvokeFunc(PrintStarTriAngle);

    /**
     * result : satisfying
     * date : 11-13 20:57
     */
     //InvokeFunc(CountingPi);

     /**
      * result : accepted
      * date : 11-25 19:31
      */
     //InvokeFunc(WriteStudentInfoToFile);

     S a[5] = {
             {88},{82},{73},{95},{80}
     },*p[5],*t;
     int i,j;
     for(i = 0;i<5;i++)
         p[i] = &a[i];
    for(i=0;i<5;i++){
        for (int j = 0; j < 5-i-1; ++j) {
            if(p[j]->score>p[j+1]->score){
                t=p[j];p[j]=p[j+1];p[j+1]=t;
            }
        }
    }
    printf("%d,%d\n",a[2].score,p[2]->score);
}

//void MyStartUpFunction() __attribute__((constructor)){
//    printf("yes!\n");
//}
